package org.hepeng.commons.spring.security.web.filter;

import org.hepeng.commons.exception.ApplicationRuntimeException;
import org.joor.Reflect;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 *
 * @author he peng
 */
public abstract class SkipOverSpringSecurityFilterChainFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if (! isSkipOver(request)) {
            filterChain.doFilter(request , response);
            return;
        }

        Class<? extends FilterChain> filterChainClass = filterChain.getClass();
        try {
            Class<?> virtualFilterChainClass =
                    Class.forName("org.springframework.security.web.FilterChainProxy$VirtualFilterChain");
            if (virtualFilterChainClass.isAssignableFrom(filterChainClass)) {
                Reflect reflect = Reflect.on(filterChain);
                Object size = reflect.field("size").get();
                reflect.set("currentPosition" , size);
            }
        } catch (Throwable t) {
            throw new ApplicationRuntimeException(t);
        }

        request = wrapRequest(request);
        response = wrapResponse(response);
        filterChain.doFilter(request , response);
    }

    protected HttpServletRequest wrapRequest(HttpServletRequest request) {
        return request;
    }


    protected HttpServletResponse wrapResponse(HttpServletResponse response) {
        return response;
    }

    protected abstract boolean isSkipOver(HttpServletRequest request);

}
